package com.vtquang.mymaps;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;

import android.R.anim;
import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.location.Address;
import android.location.Criteria;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.vtquang.mymaps.adapter.DBAddressAdapter;
import com.vtquang.mymaps.adapter.DirectionAdapter;
import com.vtquang.mymaps.adapter.SearchListAdapter;

public class Direction_Activity extends Activity implements OnClickListener,
		OnItemClickListener, OnFocusChangeListener, LocationListener {

	public enum Change {StartChange, EndChange};
	public static final String START_PLACE_KEY = "startPoint";
	public static final String END_PLACE_KEY = "endPoint";
	public static final String DIRECTION_KEY = "direction";
	private static final int SHOWDIALOG = 100;
	private static final int HIDEDIALOG = 101;
	private static final int SHOWDIALOGDIRECTION = 102;
	
	private Button btn_getDirection;
	private ImageButton btn_clearStart;
	private ImageButton btn_clearEnd;
	private EditText et_start;
	private EditText et_end;
	private EditText et_change;
	private ProgressBar progressBarStart;
	private ProgressBar progressBarEnd;
	private ListView lvAddress;

	private MyAddress addressStart = null;
	private MyAddress addressEnd = null; 

	private boolean isClickListView = false;
	private boolean isDoneStart = true;
	private boolean isDoneEnd = false; 
	private Change _change;

	private SearchListAdapter adapter;
	private ArrayList<MyAddress> listAddress;

	private int _indexThread = 0;
	private String _strSearchStart;
	private String _strSearchEnd;

	private DBAddressAdapter mDB;
	private boolean isDBOpen = false;
	
	private ImageView imageSrc;
	private ImageView imageDes;

	private ProgressDialog progressDialog;
	private Dialog dialog;
	private Direction direction;
	
	private LocationManager locationManager;
	private Location locater = new Location("current");
	
	private ImageButton []imgButtonMode = new ImageButton[3]; 
	
	private String mode[] = {"driving", "bicycling", "walking"};
	private int selectMode = 0;
	
	private Handler myHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) { 
			switch (msg.what) {
			case 0:
				listAddress.clear();
				lvAddress.setAdapter(adapter);
				break;
			case 1:
				ObjecThread obj = (ObjecThread) msg.obj;
				if (obj.index == _indexThread) {
					listAddress.add(obj.address);
					//lvAddress.setAdapter(adapter);
					adapter.notifyDataSetChanged();
				} else {
					listAddress.clear();
					adapter.notifyDataSetChanged();
					//lvAddress.setAdapter(adapter);
				}
				break;
			case 2:
				progressBarStart.setVisibility(View.INVISIBLE);
				progressBarEnd.setVisibility(View.INVISIBLE);
				break;
			case SHOWDIALOG:
				progressDialog.show();
				break;
			case HIDEDIALOG:
				progressDialog.dismiss();
				break;
			case SHOWDIALOGDIRECTION:
				if (direction._lstStep != null && direction._lstStep.size() > 0) {
					viewDialogDirection(direction._lstStep);
				}else{
					progressDialog.dismiss();
					Toast.makeText(getApplicationContext(), "Not Found!!", Toast.LENGTH_SHORT).show();
				}
				break;
			default:
				break;
			}
		}
	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_direction);

		btn_getDirection = (Button)findViewById(R.id.btnGetDirection);
		btn_clearStart = (ImageButton) findViewById(R.id.btn_clearStart);
		btn_clearEnd = (ImageButton) findViewById(R.id.btn_clearEnd);
		et_start = (EditText) findViewById(R.id.et_startpoint);
		et_end = (EditText) findViewById(R.id.et_endpoint);
		lvAddress = (ListView) findViewById(R.id.lv_dirAddess);
		progressBarStart = (ProgressBar) findViewById(R.id.progressBarStart);
		progressBarEnd = (ProgressBar) findViewById(R.id.progressBarEnd);
		imageSrc = (ImageView)findViewById(R.id.imageViewSrc);
		imageDes = (ImageView)findViewById(R.id.imageViewDes); 
		imgButtonMode[0] = (ImageButton)findViewById(R.id.imgButtonCar);
		imgButtonMode[1] = (ImageButton)findViewById(R.id.imgButtonBicycle);
		imgButtonMode[2] = (ImageButton)findViewById(R.id.imgButtonWalk);

		btn_clearStart.setOnClickListener(this);
		btn_clearEnd.setOnClickListener(this);
		btn_getDirection.setOnClickListener(this);
		imgButtonMode[0].setOnClickListener(this);
		imgButtonMode[1].setOnClickListener(this);
		imgButtonMode[2].setOnClickListener(this);
		
		lvAddress.setOnItemClickListener(this);
		progressDialog = new ProgressDialog(this);  
		
		listAddress = new ArrayList<MyAddress>();
		adapter = new SearchListAdapter(getApplicationContext(), listAddress);
		lvAddress.setAdapter(adapter);
		
		mDB = new DBAddressAdapter(this);

		et_start.addTextChangedListener(new TextWatcherStartPoint());
		et_end.addTextChangedListener(new TextWatcherEndPoint());
		et_start.setOnFocusChangeListener(this);
		et_end.setOnFocusChangeListener(this);
		et_end.requestFocus();
		et_change = et_end; 
		
		Thread thrSearch = new Thread(new ThreadGetDataBase());
		thrSearch.start();   
		
		getLocation(); 
		addressStart = new MyAddress("","", locater.getLongitude(), locater.getLatitude());
	 }

	@Override
	protected void onPause() {
		_indexThread++;
		super.onPause();
	}

	@Override
	protected void onStop() {
		if (isDBOpen) {
			mDB.close();
		}
		super.onStop();
	}

	@Override
	public void onClick(View v) {
		int id = v.getId();
		switch (id) {
		case R.id.btn_clearStart:
			_indexThread++;
			if (_strSearchStart != "") {
				et_start.setText("");
				_strSearchStart = "";
			}
			break;
		case R.id.btn_clearEnd:
			_indexThread++;
			if (_strSearchEnd != "") {
				et_end.setText("");
				_strSearchEnd = "";
			}
			break; 
		case R.id.btnGetDirection:  
			ThreadDirection runnable = new ThreadDirection(
					addressStart.get_lat(), addressStart.get_lon(),
					addressEnd.get_lat(), addressEnd.get_lon());
			Thread thead = new Thread(runnable);
			thead.start(); 
			break;
		case R.id.btnViewMap:
			dialog.dismiss();
			Intent data = new Intent(); 
			data.putExtra(DIRECTION_KEY, direction._polyLine);
			setResult(RESULT_OK, data);
			finish(); 
			break;
		case R.id.btnBack:
			dialog.dismiss();
			break;
		case R.id.imgButtonCar:
			selectMode = 0;
			setStateButton();
			break;
		case R.id.imgButtonBicycle:
			selectMode = 1;
			setStateButton();
			break;
		case R.id.imgButtonWalk:
			selectMode = 2;
			setStateButton();
			break;
		default:
			break;
		}
	}
	
	private void setStateButton(){
		for (int i = 0; i < imgButtonMode.length; i++) {
			if(i == selectMode){
				imgButtonMode[i].setBackgroundResource(R.drawable.btn_default_normal);
			}else{
				imgButtonMode[i].setBackgroundResource(R.drawable.btn_default_normal_disable);
			}
		}
	}
	
	private boolean IsDataOK(){
		return (isDoneEnd && isDoneStart);
	}

	@Override
	public void onFocusChange(View v, boolean hasFocus) {
		// TODO Auto-generated method stub
		int id = v.getId();
		switch (id) {
		case R.id.et_startpoint:
			if (hasFocus) {
				et_change = et_start;  
				_change = Change.StartChange;
			}
			break;
		case R.id.et_endpoint:
			if (hasFocus) {
				et_change = et_end;
				_change = Change.EndChange;
			}
			break; 
		default:
			break;
		}
	}

	@Override
	public void onItemClick(AdapterView<?> parent, View view, int position,
			long id) {
		MyAddress myaddress = listAddress.get(position);

		DBAddressAdapter db = new DBAddressAdapter(getApplicationContext());
		db.open();
		db.InsertAddress(myaddress);
		db.close();

		isClickListView = true;
		et_change.setText(myaddress.get_name());
		
		if(_change == Change.StartChange){
			addressStart = myaddress;
			isDoneStart = true;
			imageSrc.setImageResource(R.drawable._ic_menu_src);
		}else if(_change == Change.EndChange){
			addressEnd = myaddress;
			isDoneEnd = true;
			imageDes.setImageResource(R.drawable._ic_menu_des);
		}
		 	 
		if(IsDataOK()){
			btn_getDirection.setVisibility(View.VISIBLE);
		}
	}

	class ThreadSearch implements Runnable {
		private int index;
		private String _strSearch;

		public ThreadSearch(int a, String search) {
			index = a;
			_strSearch = search;
		}

		public ThreadSearch() {
			index = _indexThread;
		}

		@Override
		public void run() {
			Message msg = myHandler.obtainMessage(0, null);
			myHandler.sendMessage(msg);

			index = _indexThread;
			Geocoder geoCoder = new Geocoder(getApplicationContext(),
					Locale.getDefault());
			try {
				List<Address> addresses = geoCoder.getFromLocationName(
						_strSearch, 5);

				int count = addresses.size();
				if (count > 0) {
					for (int i = 0; i < count && (index == _indexThread); i++) {
						String name = "";
						String local = "";
						double lon = addresses.get(i).getLongitude();
						double lat = addresses.get(i).getLatitude();

						int maxline = addresses.get(i).getMaxAddressLineIndex();

						if (maxline >= 0)
							name += addresses.get(i).getAddressLine(0);

						for (int j = 1; j < maxline; j++) {
							local += addresses.get(i).getAddressLine(j);
							if (j < maxline - 1)
								local += ",";
							else
								local += ".";
						}

						MyAddress myaddress = new MyAddress(name, local, lon,
								lat);

						if (name.length() <= 0)
							name = addresses.get(i).getLocality();

						if (index == _indexThread) {
							ObjecThread obj = new ObjecThread();
							obj.index = index;
							obj.address = myaddress;

							msg = myHandler.obtainMessage(1, obj);
							myHandler.sendMessage(msg);
						}
					}
				}

				if (index == _indexThread) {
					msg = myHandler.obtainMessage(2, null);
					myHandler.sendMessage(msg);
				}

			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	class ThreadGetDataBase implements Runnable {
		private int index;

		public ThreadGetDataBase() {
			index = _indexThread;
		}

		@Override
		public void run() {
			Message msg = myHandler.obtainMessage(0, null);
			myHandler.sendMessage(msg);

			mDB.open();
			isDBOpen = true;

			Cursor mCursor = mDB.getAllAddress();
			int count = mCursor.getCount();
			if (count > 0) {
				mCursor.moveToLast();
				for (int i = count - 1; i >= 0 && (index == _indexThread); i--) {
					String name = mCursor.getString(1);
					String local = mCursor.getString(2);
					double lon = mCursor.getDouble(3);
					double lat = mCursor.getDouble(4);

					MyAddress myaddress = new MyAddress(name, local, lon, lat);

					if (index == _indexThread) {
						ObjecThread obj = new ObjecThread();
						obj.index = index;
						obj.address = myaddress;
						msg = myHandler.obtainMessage(1, obj);
						myHandler.sendMessage(msg);
					}

					if (!mCursor.moveToPrevious())
						break;
				}
			}

			if (index == _indexThread) {
				msg = myHandler.obtainMessage(2, null);
				myHandler.sendMessage(msg);
			}

			mCursor.close();
			mDB.close();
			isDBOpen = false;
		}
	}

	public class ObjecThread {
		public int index;
		public MyAddress address;
	}

	class TextWatcherStartPoint implements TextWatcher { 
		@Override
		public void afterTextChanged(Editable s) {
			if (isClickListView == false) {
				_strSearchStart = s.toString();

				progressBarStart.setVisibility(View.VISIBLE);
				btn_clearStart.setEnabled(_strSearchStart != ""); 
 
				Thread thrSearch;
				if (_strSearchStart.length() > 0) {
					thrSearch = new Thread(new ThreadSearch(_indexThread,
							_strSearchStart));
					isDoneStart = false; 
					imageSrc.setImageResource(R.drawable._ic_menu_src_);
					btn_getDirection.setVisibility(View.INVISIBLE);
				} else {
					thrSearch = new Thread(new ThreadGetDataBase());
					addressStart = new MyAddress("","", locater.getLongitude(), locater.getLatitude());
					isDoneStart = true; 
					imageSrc.setImageResource(R.drawable._ic_menu_src); 
					if(IsDataOK()){
						btn_getDirection.setVisibility(View.VISIBLE);
					}
				}
				thrSearch.start();
			}
			isClickListView = false;
		}

		@Override
		public void beforeTextChanged(CharSequence s, int start, int count,
				int after) {
			_indexThread++;
//			isDoneStart = false; 
//			imageSrc.setImageResource(R.drawable._ic_menu_src_);
//			btn_getDirection.setVisibility(View.INVISIBLE);
		}

		@Override
		public void onTextChanged(CharSequence s, int start, int before,
				int count) {
			progressBarStart.setVisibility(View.INVISIBLE);
		}
	}

	class TextWatcherEndPoint implements TextWatcher { 
		@Override
		public void afterTextChanged(Editable s) {
			if (isClickListView == false) {
				_strSearchEnd = s.toString();

				progressBarEnd.setVisibility(View.VISIBLE);
				btn_clearEnd.setEnabled(_strSearchEnd != "");

				Thread thrSearch;
				if (_strSearchEnd.length() > 0) {
					thrSearch = new Thread(new ThreadSearch(_indexThread,
							_strSearchEnd));
				} else {
					thrSearch = new Thread(new ThreadGetDataBase());
				}
				thrSearch.start();
			}
			isClickListView = false;
		}

		@Override
		public void beforeTextChanged(CharSequence s, int start, int count,
				int after) {
			_indexThread++;
			isDoneEnd = false; 
			imageDes.setImageResource(R.drawable._ic_menu_des_);
			btn_getDirection.setVisibility(View.INVISIBLE);
		}

		@Override
		public void onTextChanged(CharSequence s, int start, int before,
				int count) {
			progressBarEnd.setVisibility(View.INVISIBLE);
		}
	}
	
	class ThreadDirection implements Runnable {
		private double latSrc;
		private double lngSrc;
		private double latDes;
		private double lngDes;

		public ThreadDirection(double lat1, double lon1, double lat2,
				double lon2) {
			latSrc = lat1;
			lngSrc = lon1;
			latDes = lat2;
			lngDes = lon2;
		}

		@Override
		public void run() {
			progressDialog.setMessage("Load Direction ..."); 
			myHandler.sendEmptyMessage(SHOWDIALOG); 

			direction = WebProvider.getDirections(
					latSrc, lngSrc, latDes, lngDes, mode[selectMode]);  
			
			myHandler.sendEmptyMessage(SHOWDIALOGDIRECTION); 
 		}
	}
	
	private void viewDialogDirection(ArrayList<StepDirection> list) {
		myHandler.sendEmptyMessage(HIDEDIALOG); 
		
		dialog = new Dialog(Direction_Activity.this);
		dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
		dialog.setContentView(R.layout.directiondialog);
		dialog.setCancelable(false); 
		
		DirectionAdapter adapter = new DirectionAdapter(Direction_Activity.this, list); 
	 	ListView lv = (ListView) dialog.findViewById(R.id.lvDirection);
	 	Button btnViewMap = (Button)dialog.findViewById(R.id.btnViewMap);
	 	Button btnBack = (Button)dialog.findViewById(R.id.btnBack);
	 	TextView tvStartAddres = (TextView)dialog.findViewById(R.id.tvStartAddress);
	 	TextView tvEndAddress = (TextView)dialog.findViewById(R.id.tvEndAddress);
	 	TextView tvTotalDistance = (TextView)dialog.findViewById(R.id.tvTotalDistance);
	 	TextView tvTotalDuration = (TextView)dialog.findViewById(R.id.tvTotalDuration);
	 	
	 	tvStartAddres.setText("A - " + direction._startAddress);
	 	tvEndAddress.setText("B - " + direction._endAdress);
	 	tvTotalDistance.setText("Khoảng : " + direction._totalDistance);
	 	tvTotalDuration.setText("Thời gian : " + direction._totalDuration);
	 	
	 	btnViewMap.setOnClickListener(this);
	 	btnBack.setOnClickListener(this);
   
		lv.setAdapter(adapter);

		dialog.show();
	}

	@Override
	public void onLocationChanged(Location location) {
		// TODO Auto-generated method stub
		locater.set(location);
	}

	@Override
	public void onProviderDisabled(String provider) {
		// TODO Auto-generated method stub 
	}

	@Override
	public void onProviderEnabled(String provider) {
		// TODO Auto-generated method stub 
	}

	@Override
	public void onStatusChanged(String provider, int status, Bundle extras) {
		// TODO Auto-generated method stub 
	}
	
	private void getLocation() {
		locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
		Criteria criteria = new Criteria();
		criteria.setAccuracy(Criteria.ACCURACY_FINE);
		String provider = locationManager.getBestProvider(criteria, true);
		//  updates [after changes of: 5 sec. or 10 meter]
		locationManager.requestLocationUpdates(provider, 5, 10, this);

		try {
			locater.set(locationManager.getLastKnownLocation(provider));
		} catch (Exception ex) {

		}
	}
}
